package org.fhm.zdte.common.pojo;


import org.fhm.zdte.common.constant.DataTransform;
import org.fhm.zdte.common.constant.protocol.ContentType;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Base64;
import java.util.HashMap;
import java.util.function.Function;

/**
 * A response object encapsulated in a C2C or C2S process.
 *
 * @author 谭波
 * @since 2023/11/29
 */
public class Result<T> extends Request {

    public static final String SUCCESS = "SUCCESS";

    public static final String FAIL = "FAIL";

    private String status;

    private T result;

    private String message;

    private String messageNumber;

    public static Result<Void> getFailMessage(String message) {
        Result<Void> re = new Result<>();
        re.setStatus(FAIL);
        re.setMessage(message);
        return re;
    }

    public static <R> Result<R> getFailResult(R content) {
        Result<R> re = new Result<>();
        re.setStatus(FAIL);
        re.setResult(content);
        return re;
    }

    public static <R> Result<R> getFailResult(R content, String msg) {
        Result<R> re = new Result<>();
        re.setStatus(FAIL);
        re.setResult(content);
        re.setMessage(msg);
        return re;
    }

    public static Result<Void> getSuccessMessage(String msg) {
        Result<Void> successResult = getSuccessResult();
        successResult.setMessage(msg);
        return successResult;
    }

    public static Result<Void> getSuccessResult() {
        Result<Void> re = new Result<>();
        re.setStatus(SUCCESS);
        return re;
    }

    public static <R> Result<R> getSuccessResult(R content) {
        Result<R> re = new Result<>();
        re.setStatus(SUCCESS);
        re.setResult(content);
        return re;
    }

    public static Result<Void> getResultWithFile(String filePath) {
        File file = new File(filePath);
        if (!file.exists())
            return Result.getFailMessage("the file does not exist");
        if (!file.isFile())
            return Result.getFailMessage("the file is not a file");
        if (file.length() > DataTransform.FILE_SIZE_MAX)
            return Result.getFailMessage("the file transfer limit is exceeded");
        try {
            HashMap<String, Object> params = new HashMap<>();
            params.put(DataTransform.DATA, Base64.getEncoder().encodeToString(
                            Files.readAllBytes(file.toPath())
                    )
            );
            params.put(DataTransform.FILE_NAME_KEY, file.getName());
            Result<Void> result = Result.getSuccessMessage("the pull file was successful");
            result.setContentType(ContentType.FILE);
            result.setParams(params);
            return result;
        } catch (IOException e) {
            return Result.getFailMessage(e.getMessage());
        }
    }

    public static <R> Result<R> reSetResult(Result<?> result, Function<Object, R> convertContent) {
        Result<R> rResult = new Result<>();
        rResult.setResult(convertContent.apply(result.getResult()));
        rResult.setMessage(result.getMessage());
        rResult.setStatus(result.getStatus());
        return rResult;
    }

    public static boolean isSuccessful(Result<?> result) {
        return SUCCESS.equals(result.getStatus());
    }

    public static boolean isFailed(Result<?> result) {
        return FAIL.equals(result.getStatus());
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessageNumber() {
        return messageNumber;
    }

    public void setMessageNumber(String messageNumber) {
        this.messageNumber = messageNumber;
    }
}
